package org.fanximall.erp.common.tree;

import lombok.Getter;
import lombok.Setter;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author :  william
 * @version :  V1.0  created in 2024/4/22
 * 树桩结构顶层定义
 */
@Getter
@Setter
public class TreeDefinitionModel<T extends TreeDefinition>{

    /**
     * 数据id
     */
    private Long id;

    /**
     * 父id
     */
    private Long parentId;

    /**
     * 标语
     */
    private String label;

    /**
     * 数据实体
     */
    private T data;

    /**
     * 自节点
     */
    private List<TreeDefinitionModel<T>> children;


    /**
     * 构建树结构 顶层支持多个
     * @param treeDefinitionModelList 原始data
     * @return 树结构
     * @param <T> 树定义接口
     */
    @SuppressWarnings("unused")
    public static <T extends TreeDefinition> List<TreeDefinitionModel<T>> buildTreeDefinitionModel(List<T> treeDefinitionModelList) {
        if (CollectionUtils.isEmpty(treeDefinitionModelList)) {
            return null;
        }

        Map<Long, List<T>> groupByParentId = treeDefinitionModelList.stream()
                .collect(Collectors.groupingBy(TreeDefinition::getParentId));
        List<T> parent = groupByParentId.get(0L);
        if (CollectionUtils.isEmpty(parent)) {
            throw new IllegalArgumentException("No root node found");
        }

        return getTreeDefinitionModels(groupByParentId, parent);
    }



    /**
     * 构建单个树结构 顶层支持多个
     * @param treeDefinitionModelList 原始data
     * @return 树结构
     * @param <T> 树定义接口
     */
    @SuppressWarnings("unused")
    public static <T extends TreeDefinition> TreeDefinitionModel<T> buildSingleTreeDefinitionModel(List<T> treeDefinitionModelList) {
        if (CollectionUtils.isEmpty(treeDefinitionModelList)) {
            return null;
        }

        Map<Long, List<T>> groupByParentId = treeDefinitionModelList.stream()
                .collect(Collectors.groupingBy(TreeDefinition::getParentId));
        List<T> parent = groupByParentId.get(0L);
        if (CollectionUtils.isEmpty(parent) || parent.size() >1 ) {
            throw new IllegalArgumentException("No root node found");
        }
        T parentData = parent.get(0);
        TreeDefinitionModel<T> childModel = new TreeDefinitionModel<>();
        childModel.build(parentData);
        buildChildrenList(childModel, groupByParentId);
        return childModel;
    }

    /**
     * 获取树结构
     * @param groupByParentId parent分组
     * @param childrenList 子节点list
     * @return 树结构
     * @param <T> TreeDefinition接口
     */
    private static <T extends TreeDefinition> List<TreeDefinitionModel<T>> getTreeDefinitionModels(Map<Long, List<T>> groupByParentId, List<T> childrenList) {
        List<TreeDefinitionModel<T>> treeDefinitionModels = new ArrayList<>();
        for (T child : childrenList) {
            TreeDefinitionModel<T> childModel = new TreeDefinitionModel<>();
            childModel.build(child);
            buildChildrenList(childModel, groupByParentId);
            treeDefinitionModels.add(childModel);
        }
        return treeDefinitionModels;
    }


    /**
     * 子节点树构建
     * @param treeDefinitionModel 树节点
     * @param groupByParentId   parent分组
     * @param <T> TreeDefinition接口
     */
    private static <T extends TreeDefinition> void buildChildrenList(TreeDefinitionModel<T> treeDefinitionModel,
                                                                     Map<Long, List<T>> groupByParentId) {
        List<T> childrenList = groupByParentId.get(treeDefinitionModel.getId());
        if (CollectionUtils.isEmpty(childrenList)) {
            return;
        }
        List<TreeDefinitionModel<T>> treeDefinitionModels = getTreeDefinitionModels(groupByParentId, childrenList);
        treeDefinitionModel.setChildren(treeDefinitionModels);

    }




    public void build(T data) {
        this.parentId = data.getParentId();
        this.id = data.getId();
        this.label = data.getLabel();
        this.data = data;
    }

}
